package cn.flying.base.common.utils;

import java.util.HashMap;
import java.util.Map;

import cn.flying.base.common.enums.RtCodeEnum;
import cn.flying.base.common.exception.FlyingException;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @description: JSON 操作工具类
 * @author: lvyong
 * @date: 2022年04月02日 22:30
 * @version: 1.0
 */
public class JsonUtil {

    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
    }

    public JsonUtil() {
    }

    /**
     * JSON 序列化
     * @param obj
     * @return
     */
    public static String serializer(Object obj) {
        try {
            if (obj == null) {
                return null;
            } else if (obj instanceof String) {
                return (String) obj;
            } else {
                return objectMapper.writeValueAsString(obj);
            }
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "序列化失败", e);
        }
    }

    /**
     * JSON 序列化
     * @param obj
     * @return
     */
    public static String serialIgnoreNull(Object obj) {
        try {
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "序列化失败", e);
        }
    }

    /**
     * JSON 反序列化
     * @param jsonString
     * @param clazz
     * @return
     */
    public static <T> T deserialize(String jsonString, Class<T> clazz) {
        try {
            objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return objectMapper.readValue(jsonString, clazz);
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "反序列化失败", e);
        }
    }

    /**
     * JSON 反序列化
     * @param jsonString
     * @param type
     * @return
     */
    public static Object deserialize(String jsonString, TypeReference type) {
        try {
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return objectMapper.readValue(jsonString, type);
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "反序列化失败", e);
        }
    }

    /**
     * 字符串转换为 Map<String, Object>
     * @param jsonString
     * @return
     */
    public static <T> Map<String, Object> parseToMap(String jsonString) {
        try {
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return objectMapper.readValue(jsonString, Map.class);
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "反序列化失败", e);
        }
    }

    /**
     * 字符串转换为 Map<String, T>
     * @param jsonString
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> Map<String, T> parseToMap(String jsonString, Class<T> clazz) {
        try {
            Map<String, Map<String, Object>> map = (Map<String, Map<String, Object>>) objectMapper.readValue(jsonString, new TypeReference<Map<String, T>>() {
            });
            Map<String, T> result = new HashMap<>();
            for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
                result.put(entry.getKey(), mapToBean(entry.getValue(), clazz));
            }
            return result;
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "反序列化失败", e);
        }

    }

    /**
     * 将 Map 转换为 JavaBean
     * @param map
     * @param clazz
     * @return
     */
    public static <T> T mapToBean(Map map, Class<T> clazz) {
        return objectMapper.convertValue(map, clazz);
    }

    /**
     * 将 Map 转换为 JSON
     *
     * @param map
     * @return
     */
    public static String mapToJson(Map map) {
        try {
            return objectMapper.writeValueAsString(map);
        } catch (Exception e) {
            throw new FlyingException(RtCodeEnum.R90000.getCode(), "序列化失败", e);
        }
    }

    /**
     * 将 JSON 对象转换为 JavaBean
     * @param obj
     * @param clazz
     * @return
     */
    public static <T> T objToBean(Object obj, Class<T> clazz) {
        return objectMapper.convertValue(obj, clazz);
    }


}
